#!/usr/bin/env bash

# help menu
usage()
{
	echo "Usage: $0 [options] [output file]"
	echo "Creates bootable GRUB images from Unikraft kernel images."
	echo ""
	echo "  -h                         Display help and exit"
	echo "  -f                         Output format (supported: iso)"
	echo "  -k                         Path to the Unikraft kernel image"
	echo "  -a                         Kernel command-line parameters (optional)"
	echo "  -i                         Path to initrd cpio file (optional)"
	exit 1
}

# default options
OPTFORMAT="iso"
OPTCMDLINE=""

# cleanup
BUILDDIR=
sighandler_exit()
{
	if [ ! -z "${BUILDDIR}" -a -d "${BUILDDIR}" ]; then
		rm -rf "${BUILDDIR}"
	fi
}

# process options
while getopts "hk:i:f:a:" OPT; do
	case "${OPT}" in
		h)
			usage
			;;
		f)
			OPTFORMAT="${OPTARG}"
			;;
		k)
			OPTKERNELIMG="${OPTARG}"
			;;
		a)
			OPTCMDLINE="${OPTARG}"
			;;
		i)
			OPTINITRD="${OPTARG}"
			;;
		*)
			usage
			;;
	esac
done
shift $((OPTIND-1))

# validate arguments
if [[ -z "${OPTKERNELIMG}" ]]; then
	echo "Missing path to kernel image ('-k')" 1>&2
	usage
fi
if [[ -z "${1}" ]]; then
	echo "Missing path to output image" 1>&2
	usage
fi
if [ ! -f "${OPTKERNELIMG}" ]; then
	echo "${OPTKERNELIMG} does not exist or is not a file" 1>&2
	exit 1
fi
if [ ! -z "${OPTINITRD}" -a ! -f "${OPTINITRD}" ]; then
	echo "${OPTINITRD} does not exist or is not a file" 1>&2
	exit 1
fi

# Register exit handler and create BUILDDIR
trap sighandler_exit exit
BUILDDIR="$( mktemp -d )"
if [ $? -ne 0 -o -z "${BUILDDIR}" -o ! -d "${BUILDDIR}" ]; then
	echo "Failed to create temporary directory" 1>&2
	exit 1
fi

OPTKERNELNAME="${OPTKERNELIMG##*/}"
OPTINITRDNAME="${OPTINITRD##*/}"

case "${OPTFORMAT}" in
	# generate grub iso image
	iso)
		# configure grub
		mkdir -p "${BUILDDIR}/boot/grub"

		if [ ! -z "${OPTINITRD}" ]; then
			GRUB_CFG_INITRD="module /boot/${OPTINITRDNAME}"
			cp "${OPTINITRD}" "${BUILDDIR}/boot/${OPTINITRDNAME}" || exit 1
		fi
		cp "${OPTKERNELIMG}" "${BUILDDIR}/boot/" || exit 1

		cat >"${BUILDDIR}/boot/grub/grub.cfg" <<EOF
set default=0
set timeout=0

menuentry "${OPTKERNELNAME}" {
	multiboot /boot/${OPTKERNELNAME} /${OPTKERNELNAME} ${OPTCMDLINE}
	${GRUB_CFG_INITRD}
	boot
}
EOF

		# build grub image
		GRUB_INSTALL_MSGS=$( grub-mkrescue -o "$1" --install-modules="multiboot" --fonts="" --themes="" --locales="" "${BUILDDIR}/" 2>&1 )
		if [ $? != 0 ]; then
			printf '%s\n' "$GRUB_INSTALL_MSGS" 1>&2
			exit 1
		fi
		;;
	*)
		echo -e "\"${OPTFORMAT}\" not a supported format." 1>&2
		usage
		;;
esac
